package org.tjc.net.manager.bean;

import org.apache.commons.lang3.StringUtils;
import org.tjc.net.manager.exception.ParseHttpException;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author: tjc
 * @description
 * @Date Created in 17:27 2020-11-25
 */
public class HttpRequest {
    private String HttpMethod;

    private String url;

    private String domain;

    private String version;

    private String protocol;

    private Map<String, String> headers;

    private String body;



    public static String METHOD_GET = "GET";
    public static String METHOD_POST = "POST";

    public static String HTTP11 = "HTTP/1.1";

    private static String LINE_SEPARATOR = "\r\n";


    public static HttpRequest parse(String message) {
        HttpRequest request = new HttpRequest();

        int firstLineEnd = message.indexOf(LINE_SEPARATOR);
        if (firstLineEnd < 0) {
            throw new ParseHttpException("Http message content error for:" + message);
        }
        String requestLine = message.substring(0, firstLineEnd);

        int index1 = requestLine.indexOf(' ');
        if (index1 < 0) {
            throw new ParseHttpException("Http message content error for:" + message);
        }
        int index2 = requestLine.indexOf(' ', index1 + 1);
        if (index2 < 0) {
            throw new ParseHttpException("Http message content error for:" + message);
        }

        String method = requestLine.substring(0, index1);
        String url = requestLine.substring(index1 + 1, index2);
        String version = requestLine.substring(index2 + 1);

        checkMethodFormat(method);


        Map<String, String> headers = new HashMap<>();

        int headerIndex = firstLineEnd + LINE_SEPARATOR.length();

        while (true) {
            int nextLineEnd = message.indexOf(LINE_SEPARATOR, headerIndex);
            String headerStr = message.substring(headerIndex, nextLineEnd);
            if ("".equals(headerStr)) {
                headerIndex = nextLineEnd + LINE_SEPARATOR.length();
                break;
            }
            int mid = headerStr.indexOf(':');
            if(mid == -1) {
                throw new RuntimeException("http message parse header fail: " + headerStr);
            }
            String key = headerStr.substring(0, mid);
            checkHeader(key);
            String value = headerStr.substring(mid + 1);
            headers.put(StringUtils.trimToEmpty(key), StringUtils.trimToEmpty(value));

            headerIndex = nextLineEnd + LINE_SEPARATOR.length();
        }
        int bodyIndex = headerIndex;
        String body = message.substring(bodyIndex);


        request.setUrl(url);
        request.setHttpMethod(method);
        request.setVersion(version);
        request.setHeaders(headers);
        request.setBody(body);

        return request;
    }

    public String toMessage() {
        String firstLine = this.getHttpMethod() + " " + this.getUrl() + " " + this.getVersion() + "\r\n";
        String headersStr = "";
        for (Map.Entry<String, String> header : this.getHeaders().entrySet()) {
            headersStr += header.getKey() + ": " + header.getValue() + "\r\n";
        }
        String Bodysporater = "\r\n";
        String body = this.getBody();

        return firstLine + headersStr + Bodysporater + body;
    }

    private static boolean checkHeader(String key) {
        switch (key) {
            default:
                return true;
        }
    }

    private static void checkMethodFormat(String method) {
        switch (method) {
            case "GET":
            case "POST":
                return;
            default:
                throw new ParseHttpException("unsupport http method.");
        }
    }

    public static boolean isHttp(HttpRequest request) {
        return request.getVersion().equals(HTTP11);
    }

    public String getHttpMethod() {
        return HttpMethod;
    }

    public void setHttpMethod(String httpMethod) {
        HttpMethod = httpMethod;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getDomain() {
        return domain;
    }

    public void setDomain(String domain) {
        this.domain = domain;
    }


    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public String getProtocol() {
        return protocol;
    }

    public void setProtocol(String protocol) {
        this.protocol = protocol;
    }

    public Map<String, String> getHeaders() {
        return headers;
    }

    public void setHeaders(Map<String, String> headers) {
        this.headers = headers;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

    public String getHeader(String key) {
        return headers.get(key);
    }

    public void setHeader(String key, String value) {
        headers.put(key, value);
    }
}
